package cooperate

import (
	"fmt"

	"gddgame.cc/galaxy/common/feature/orbit/chess_protocol"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/common/service/pathfinding"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/serialize"
)

//go:generate msgp

const (
	AccountDataType    = "account"
	NodeDataType       = "node"
	PathNodeDataType   = "path"
	ForceDataType      = "force"
	MapContentDataType = "mapContent"
	ManageDataType     = "manage" // 下放管理
)
const (
	AccountType  structure.PublicDataType = 1
	NodeType     structure.PublicDataType = 2
	PathNodeType structure.PublicDataType = 3
	ForceType    structure.PublicDataType = 4

	MapContentType structure.PublicDataType = 129
	ManageType     structure.PublicDataType = 130
)

type Operate byte

const (
	_ Operate = iota
	CreateOperate
	BatchUpdateOperate
	DeleteOperate
	ResetOperate
	EventOperate
)

type NoticeProtocol byte

const (
	_ NoticeProtocol = iota
	CreateNoticeProtocol
	UpdateNoticeProtocol
	DeleteNoticeProtocol
)

const (
	_ structure.EventMode = iota
	OperateMode
	TaskMode
	ScheduleMode
	BindEventMode
	QueryMode
)

type UpdateOperate byte

const (
	ChangeData UpdateOperate = iota
	ChangeDataSync
	ChangeDateTime
	ChangePosition
	ChangeIgnore
	ChangeInherit
	ChangeDataGreater
	ChangeDataLesser
	ChangeDataGreaterSync
	ChangeDataLesserSync
	IncrData
	IncrDataSync
	IncrDataGreater
	IncrDataLesser
	IncrDataGreaterSync
	IncrDataLesserSync
	ChangeList
	ChangeListTime
	IncrList
	IncrFromList
	AddSet
	RemoveSet
	ResetSet
	AddSorted
	RemoveSorted
	ResetSorted
	AddTimeSorted
	RemoveTimeSorted
	ClearTimeSorted
	ResetTimeSorted

	PushSchedule
	ResetSchedule // 重置时间
	RemoveSchedule
	ChangeParamSchedule
	HoldSchedule // 变更内容

	BindEvent
	//LinkEvent
	ClearEvent
	//UnLinkEvent

	AddTask

	AddDepend
	RemoveDepend

	AddRelation
	RemoveRelation
	AddLink
	RemoveLink
	AddToLink
	RemoveFromLink
	AddTimeLink
	RemoveTimeLink
	AddToTimeLink
	RemoveFromTimeLink
)

const (
	Id       = "id"
	Position = "position"
	Ignore   = "ignore"
	MapNoId  = "mapNoId"
	Health   = "health"
	Identity = "identity"
	Key      = "key"  // 抽象类型key
	Range    = "rang" // 同步范围：低位到高位，每层开关，支持8层
	//Location = "location"
)

const (
	_ structure.ScheduleLogic = iota
	OnceSchedule
	RepeatSchedule
	RepeatEverySchedule
	MoveSchedule
	TouchSchedule
	CustomSchedule
)

type CheckType byte

const (
	_ CheckType = iota
	ExistCheck
	PositionEqualCheck
	PositionUnEqualCheck
	DataCheck
	EqualCheck
	GreaterCheck
	LessCheck
	ListEqualCheck
	ListGreaterCheck
	ListLessCheck
	SetExistCheck
	SetNoExistCheck
	SortedExistCheck
	SortedNoExistCheck
	SortedGreaterCheck
	SortedLessCheck
	SustainTimeExistCheck
	SustainTimeNoExistCheck
)

type UpdateMode byte

const (
	_ UpdateMode = iota
	CreateUpdateMode
	ResetUpdateMode
	DeleteUpdateMode
	ClearUpdateMode
)

type LogicType byte

type MoveStatus byte

type PropType string

const (
	InstancePropType PropType = "instanceProp"
)

var (
	MapContentField = NewFieldsDefine(MapContentType, MapContentDataType).
		SetMap(true)
)

//msgp:tuple DataNode
type DataNode struct {
	Position []byte `json:"position" msg:"position"`
	Type     byte   `json:"type" msg:"type"`
}

//msgp:tuple DataDefineNode
type DataDefineNode struct {
	Position []byte `json:"position" msg:"position"`
	Key      string `json:"key" msg:"key"`
}

//msgp DataDefineNodeSlice
type DataDefineNodeSlice []DataDefineNode

func (ps *DataDefineNodeSlice) UnSerialize(data []byte) error {
	_, err := ps.UnmarshalMsg(data)
	return err
}

//msgp:tuple RangeDefineNode
type RangeDefineNode struct {
	Position []byte   `json:"position" msg:"position"`
	Key      string   `json:"key" msg:"key"`
	Range    [][]byte `json:"range" msg:"range"`
}

//msgp:tuple MapData
type MapData struct {
	Size      []byte           `json:"size" msg:"size"`
	Center    []byte           `json:"center" msg:"center"`
	Block     []byte           `json:"block" msg:"block"`
	Mode      byte             `json:"mode" msg:"mode"`
	DataNodes []DataNode       `json:"dataNodes" msg:"dataNodes"`
	Init      []OperateData    `json:"init" msg:"init"`
	Schedule  *ScheduleContent `json:"schedule" msg:"schedule"`
	Boundary  [][]byte         `json:"boundary" msg:"boundary"`
	Extend    []byte           `json:"extend" msg:"extend"`

	SizeVector2   *pathfinding.Vector2 `json:"-" msg:"-"`
	CenterVector2 *pathfinding.Vector2 `json:"-" msg:"-"`
}

//msgp:tuple MapInfo
type MapInfo struct {
	Data             []byte                 `json:"data" msg:"data"`
	NodeCostList     []pathfinding.NodeCost `json:"nodeCostList" msg:"nodeCostList"`
	MessageRangeList []uint16               `json:"messageRangeList" msg:"messageRangeList"`
	Content          []string               `json:"content" msg:"content"`
}

//msgp:tuple Sustain
type Sustain struct {
	Type     int           `json:"type" msg:"type"`
	Params   []interface{} `json:"params" msg:"params"`
	Start    int64         `json:"start" msg:"start"`
	Time     int64         `json:"time" msg:"time"`
	CanBreak bool          `json:"can_break" msg:"can_break"`
	Schedule string        `json:"schedule" msg:"schedule"`
}

func NewSustainByte(data []byte) *Sustain {
	if data == nil {
		return nil
	}
	sustain := &Sustain{}
	if len(data) == 0 {
		return sustain
	}
	_, err := sustain.UnmarshalMsg(data)
	if err != nil {
		fmt.Println("sustain", err, data)
	}
	return sustain
}

func NewSustainBy(obj interface{}) *Sustain {
	if obj == nil {
		return nil
	}
	switch t := obj.(type) {
	case *Sustain:
		return t
	case string:
		return NewSustainByte(utils.ToBytes(t))
	case []byte:
		return NewSustainByte(t)
	}
	v := &Sustain{}
	os := utils.ToInterfaceSlice(obj)
	if os == nil {
		return nil
	}
	v.Type = utils.ToInt(os[0])
	v.Params = utils.ToInterfaceSlice(os[1])
	v.Start = utils.ToInt64(os[2])
	v.Time = utils.ToInt64(os[3])
	v.CanBreak = utils.ToBool(os[4])
	return v
}

func (a *Sustain) Bytes() []byte {
	b, _ := a.MarshalMsg(nil)
	return b
}

//msgp:tuple MapNode
type MapNode struct {
	MapNoId  string `json:"mapNoId" msg:"mapNoId"`
	Position []byte `json:"position" msg:"position"`
}

//msgp:tuple UpdateField
type UpdateField struct {
	Key   string      `json:"key" msg:"key"`
	Value interface{} `json:"value" msg:"value"`
}

//msgp:tuple UpdateEvent
type UpdateEvent struct {
	Key   string `json:"key" msg:"key"`
	Value []byte `json:"value" msg:"value"`
}

//msgp UpdateFieldSlice
type UpdateFieldSlice []UpdateField

//msgp:tuple UpdateContent
type UpdateContent struct {
	*chess_protocol.UpdatePublicData `json:"data" msg:"data"`

	Props      []UpdateField    `json:"props" msg:"props"`
	Dependents []*DependentItem `json:"dependents" msg:"dependents"`

	Event   []structure.EventData `json:"event" msg:"event"`
	Mode    UpdateMode            `json:"delete" msg:"delete"`
	Inherit bool                  `json:"inherit" msg:"inherit"`
}

//msgp:tuple NoticeContent
type NoticeContent struct {
	OldAccountId int                `json:"old" msg:"old"`
	NewAccountId int                `json:"new" msg:"new"`
	Data         structure.BaseData `json:"data" msg:"data"`
	Content      UpdateContent      `json:"content" msg:"content"`
}

//msgp:tuple UpdateNotice
type UpdateNotice struct {
	MapNoId string          `json:"map_no_id" msg:"map_no_id"`
	Node    string          `json:"node" msg:"node"`
	List    []NoticeContent `json:"data" msg:"data"`
}

//msgp:tuple Notice
type Notice struct {
	MapNoId   string `json:"map_no_id" msg:"map_no_id"`
	AccountId int    `json:"account_id" msg:"account_id"`
	Event     byte   `json:"event" msg:"event"`
	Content   []byte `json:"content" msg:"content"`
}

//msgp:tuple Queue
type Queue struct {
	Content    OperateContent
	TargetTime int64
}

//msgp:tuple TaskCallback
type TaskCallback struct {
	Node string `json:"node" msg:"node"`
	Uuid string `json:"uuid" msg:"uuid"`
}

//msgp:tuple DataMessage
type DataMessage struct {
	Event   byte          `json:"event" msg:"event"`
	Content []byte        `json:"content" msg:"content"`
	Params  []interface{} `json:"params" msg:"params"`
}

func (message *DataMessage) ToChess() *chess_protocol.Message {
	return &chess_protocol.Message{
		Event:   message.Event,
		Content: message.Content,
		Params:  message.Params,
	}
}

//msgp:tuple DependentItem
type DependentItem struct {
	Key    string              `json:"key" msg:"key"`
	Depend *structure.BaseData `json:"depend" msg:"depend"`
}

//msgp:tuple CreateOperateData
type CreateOperateData struct {
	From       *structure.BaseData           `json:"from" msg:"from"`
	Data       structure.BaseData            `json:"data" msg:"data"`
	Position   []byte                        `json:"position" msg:"position"`
	InfoKey    []string                      `json:"info_key" msg:"info_key"`
	Infos      []interface{}                 `json:"infos" msg:"infos"`
	ExtendKey  []string                      `json:"extend_key" msg:"extend_key"`
	Extends    [][]chess_protocol.ExtendItem `json:"extends" msg:"extends"`
	Dependents []*DependentItem              `json:"dependents" msg:"dependents"`

	updateOperates []UpdateOperateContent
	accountId      int
}

//msgp:tuple UpdateOperateData
type UpdateOperateData struct {
	From     *structure.BaseData    `json:"from" msg:"from"`
	Data     structure.BaseData     `json:"data" msg:"data"`
	Operates []UpdateOperateContent `json:"operates" msg:"operates"`
	Message  *DataMessage           `json:"message" msg:"message"`
	Checks   [][]CheckData          `json:"checks" msg:"checks"`
}

//msgp:tuple DeleteOperateData
type DeleteOperateData struct {
	From     *structure.BaseData      `json:"from" msg:"from"`
	DataType structure.PublicDataType `json:"data_type" msg:"data_type"`
	Id       interface{}              `json:"id" msg:"id"`
}

//msgp:tuple ResetOperateData
type ResetOperateData struct {
	From       *structure.BaseData `json:"from" msg:"from"`
	Data       structure.BaseData  `json:"data" msg:"data"`
	InfoKey    []string            `json:"info_key" msg:"info_key"`
	Infos      []interface{}       `json:"infos" msg:"infos"`
	Dependents []*DependentItem    `json:"dependents" msg:"dependents"`

	updateOperates []UpdateOperateContent
}

//msgp:tuple EventOperateData
type EventOperateData struct {
	Data    structure.BaseData  `json:"data" msg:"data"`
	Event   byte                `json:"event" msg:"event"`
	Mode    structure.EventMode `json:"mode" msg:"mode"`
	Content []byte              `json:"content" msg:"content"`

	eventData *structure.EventData `json:"-" msg:"-"`
}

//msgp:tuple UpdateOperateContent
type UpdateOperateContent struct {
	Key     string        `json:"key" msg:"key"`
	Index   int           `json:"index" msg:"index"`
	Value   interface{}   `json:"value" msg:"value"`
	Operate UpdateOperate `json:"operate" msg:"operate"`

	Time      int64       `json:"-" msg:"-"`
	SyncValue interface{} `json:"-" msg:"-"`
	// 自定义的更新属性
	// 扩展before和after时，可以根据更新操作，自动转换关联影响的同步属性
	Props map[string]interface{} `json:"-" msg:"-"`

	// 建立operate上下层的关系
	PassValue interface{} `json:"-" msg:"-"`
}

//msgp:tuple OperateData
type OperateData struct {
	Operate Operate `json:"operate" msg:"operate"`
	Data    []byte  `json:"data" msg:"data"`

	inline   serialize.IStruct `json:"-" msg:"-"`
	IdString string            `json:"-" msg:"-"`
}

func NewOperateData(operate Operate, inline serialize.IStruct) OperateData {
	b, _ := inline.MarshalMsg(nil)
	return OperateData{
		Operate: operate,
		Data:    b,
	}
}

func (od *OperateData) Format() *OperateData {
	if od.inline != nil {
		b, _ := od.inline.MarshalMsg(nil)
		od.Data = b
	}
	return od
}

//msgp OperateDataSlice
type OperateDataSlice []OperateData

//msgp:tuple OperateMessage
type OperateMessage struct {
	Data     *structure.BaseData `json:"data" msg:"data"`
	Message  *DataMessage        `json:"message" msg:"message"`
	Position []byte              `json:"position" msg:"position"`

	// 持久化
	Persistent bool `json:"-" msg:"-"`
}

//msgp:tuple OperateContent
type OperateContent struct {
	Key      string              `json:"key" msg:"key"`
	MapNoId  string              `json:"mapNoId" msg:"mapNoId"`
	Checks   [][]CheckData       `json:"checks" msg:"checks"`
	From     *structure.BaseData `json:"from" msg:"from"`
	Target   *structure.BaseData `json:"target" msg:"target"`
	Operates []OperateData       `json:"operates" msg:"operates"`
	Message  *OperateMessage     `json:"message" msg:"message"`
}

func (content *OperateContent) Equal(other interface{}) bool {
	return false
}

func (content *OperateContent) MergeUpdate(slot *serialize.Mps, update *UpdateOperateData) bool {
	for index, _ := range content.Operates {
		if content.Operates[index].Operate == BatchUpdateOperate {
			var updateOperateData UpdateOperateData
			if content.Operates[index].inline == nil {
				slot.Clear()
				_ = slot.Set(&updateOperateData)
				if err := slot.Unmarshal(content.Operates[index].Data); err != nil {
					fmt.Println("merge batch update", err)
				}
				content.Operates[index].inline = &updateOperateData
			} else {
				updateOperateData = *content.Operates[index].inline.(*UpdateOperateData)
			}
			if update.Data.Equal(&updateOperateData.Data) {
				updateOperateData.Operates = append(updateOperateData.Operates, update.Operates...)
				b, _ := updateOperateData.MarshalMsg(nil)
				content.Operates[index].Data = b
				return true
			}
		}
	}
	return false
}

//msgp:tuple TaskContent
type TaskContent struct {
	Checks  [][]CheckData       `json:"checks" msg:"checks"`
	From    *structure.BaseData `json:"from" msg:"from"`
	Task    structure.TaskEvent `json:"task" msg:"task"`
	Content []byte              `json:"content" msg:"content"`
}

//msgp:tuple ScheduleContent
type ScheduleContent struct {
	Checks   [][]CheckData           `json:"checks" msg:"checks"`
	From     *structure.BaseData     `json:"from" msg:"from"`
	Target   *structure.BaseData     `json:"target" msg:"target"`
	Schedule structure.ScheduleLogic `json:"schedule" msg:"schedule"`
	Key      string                  `json:"key" msg:"key"`
	Time     int64                   `json:"time" msg:"time"`
	Content  []byte                  `json:"content" msg:"content"`
	Delay    int                     `json:"delay" msg:"delay"`
}

//msgp:tuple EventBody
type EventBody struct {
	Data   structure.BaseData `json:"data" msg:"data"`
	Events []byte             `json:"bytes" msg:"bytes"`
}

//msgp:tuple EventContent
type EventContent struct {
	Checks  [][]CheckData `json:"checks" msg:"checks"`
	Current []byte        `json:"current" msg:"current"`
	Events  []EventBody   `json:"events" msg:"events"`
}

//msgp:tuple QueryContent
type QueryContent struct {
	Checks    [][]CheckData `json:"checks" msg:"checks"`
	AccountId int           `json:"accountId" msg:"accountId"`
	Identity  int           `json:"identity" msg:"identity"`
	Event     byte          `json:"event" msg:"event"`
	Params    []interface{} `json:"params" msg:"params"`
}

//msgp:tuple OnceScheduleContent
type OnceScheduleContent struct {
	Event structure.EventData `json:"event" msg:"event"`
}

//msgp:tuple RepeatScheduleContent
type RepeatScheduleContent struct {
	Repeat  int64               `json:"repeat" msg:"repeat"`
	EndTime int64               `json:"end_time" msg:"end_time"`
	Event   structure.EventData `json:"event" msg:"event"`
}

//msgp:tuple RepeatEveryScheduleContent
type RepeatEveryScheduleContent struct {
	Checks    [][]CheckData          `json:"checks" msg:"checks"`
	Repeat    int64                  `json:"repeat" msg:"repeat"`
	EndTime   int64                  `json:"end_time" msg:"end_time"`
	DependKey string                 `json:"depend_key" msg:"depend_key"`
	Operates  []UpdateOperateContent `json:"operates" msg:"operates"`
}

type MoveObject interface {
	GetSelfMask() int
	GetOtherMask() int
}

//msgp:tuple MoveScheduleContent
type MoveScheduleContent struct {
	Plan            [][]byte              `json:"plan" msg:"plan"`
	PlanIndex       byte                  `json:"planIndex" msg:"planIndex"`
	Positions       [][]byte              `json:"positions" msg:"positions"`
	Index           byte                  `json:"index" msg:"index"`
	SelfMask        int                   `json:"self_mask" msg:"self_mask"`
	OtherMask       int                   `json:"other_mask" msg:"other_mask"`
	Filter          [][]byte              `json:"filter" msg:"filter"`
	TargetPositions [][]byte              `json:"target_positions" msg:"target_positions"`
	Status          MoveStatus            `json:"status" msg:"status"`
	Type            LogicType             `json:"type" msg:"type"`
	Logic           []byte                `json:"logic" msg:"logic"`
	LastPosition    []byte                `json:"last_position" msg:"last_position"`
	Touch           *TouchScheduleContent `json:"touch" msg:"touch"`
}

//msgp:tuple TouchScheduleContent
type TouchScheduleContent struct {
	Times    int                  `json:"times" msg:"times"`
	Position []byte               `json:"position" msg:"position"`
	Type     LogicType            `json:"type" msg:"type"`
	Logic    []byte               `json:"logic" msg:"logic"`
	Target   *structure.BaseData  `json:"target" msg:"target"`
	Move     *MoveScheduleContent `json:"move" msg:"move"`
}

//msgp:tuple CustomScheduleContent
type CustomScheduleContent struct {
	Type  LogicType `json:"type" msg:"type"`
	Logic []byte    `json:"logic" msg:"logic"`
	Async bool      `json:"async" msg:"async"`
}

type TouchTarget struct {
	PropsInstance `json:"-" msg:"-"`

	Identity int    `json:"-" msg:"-"`
	TypeId   int    `json:"-" msg:"-"`
	Position []byte `json:"-" msg:"-"`
	Distance int    `json:"-" msg:"-"`
}

func (target *TouchTarget) Equals(data *structure.BaseData) bool {
	if data == nil {
		return false
	}
	if target.GetDataType() != data.DataType {
		return false
	}
	if data.Id == nil {
		return false
	}
	if utils.ToString(target.GetId()) != utils.ToString(data.Id) {
		return false
	}
	return true
}

func (target *TouchTarget) Value() []interface{} {
	return []interface{}{target.GetDataType(), target.GetId()}
}

//msgp:tuple CheckData
type CheckData struct {
	Data   structure.BaseData `json:"data" msg:"data"`
	Checks []CheckContent     `json:"checks" msg:"checks"`
}

//msgp CheckDataSliceTwo
type CheckDataSliceTwo [][]CheckData

//msgp:tuple CheckContent
type CheckContent struct {
	Check CheckType   `json:"check" msg:"check"`
	Key   string      `json:"key" msg:"key"`
	Index int         `json:"index" msg:"index"`
	Value interface{} `json:"value" msg:"value"`
}

//msgp:tuple ModeExtend
type ModeExtend struct {
	Params []interface{} `json:"params" msg:"params"`

	Content       serialize.IStruct  `json:"-" msg:"-"`
	MapNoId       string             `json:"-" msg:"-"`
	Checks        [][]CheckData      `json:"-" msg:"-"`
	Position      []byte             `json:"-" msg:"-"`
	Persistent    bool               `json:"-" msg:"-"`
	UpdateOperate *UpdateOperateData `json:"-" msg:"-"`
}

func NewModeExtend(params []interface{}, mapNoId string, checks [][]CheckData, position []byte) *ModeExtend {
	p := &ModeExtend{
		Params: params,

		MapNoId:  mapNoId,
		Checks:   checks,
		Position: position,
	}
	return p
}

func NewPositionModeExtend(mapNoId string, position []byte) *ModeExtend {
	p := &ModeExtend{
		MapNoId:  mapNoId,
		Position: position,
	}
	return p
}

//msgp PositionSlice
type PositionSlice [][]byte

func NewPositions(b []byte) [][]byte {
	positions := PositionSlice{}
	_, _ = positions.UnmarshalMsg(b)
	return positions
}

func NewPositionsBy(obj interface{}) PositionSlice {
	switch t := obj.(type) {
	case PositionSlice:
		return t
	case []byte:
		return NewPositions(t)
	case string:
		return NewPositions(utils.ToBytes(t))
	}
	v := utils.ToBytesSlice(obj)
	return v
}

func (ps *PositionSlice) Bytes() []byte {
	b, _ := ps.MarshalMsg(nil)
	return b
}

func (ps *PositionSlice) UnSerialize(data []byte) error {
	_, err := ps.UnmarshalMsg(data)
	return err
}

type ExtendFunc func(execute *structure.Execute, conn structure.SafeConn, instance PropsInstance, extend structure.ExtendType) interface{}

type FieldDefine struct {
	PropType    PropType
	Persistence bool
	Local       bool
}

type ExtendDefine struct {
	Extend structure.ExtendType
	fun    ExtendFunc

	AutoClean bool
}

type DependDefine struct {
	Key        string
	Be         *BeDependDefine
	IsPosition bool
	IsManage   bool
	IsNo       bool
	IsId       bool
}

type BeDependDefine struct {
	Index              int
	BeDepend           string
	BeDependType       structure.PublicDataType
	BeDependIsPosition bool
	BeDependIsNo       bool
	BeDependIsId       bool
	Depend             string
	DependType         structure.PublicDataType
	DependIsPosition   bool
	DependIsNo         bool
	DependIsId         bool
	IsChess            bool
}

type FieldsDefine struct {
	DataDefined    `json:"-" msg:"-"`
	DataType       structure.PublicDataType
	DataKey        string
	inlinePropType PropType

	// 是否是坐标类型
	IsPosition bool
	// 是否划分地图
	IsMap bool
	// 是否序号
	IsNo bool
	// 是否id
	IsId bool
	// 是否需要同步
	IsChess bool
	// 是否是管理对象
	IsManage bool

	DependMap   map[string]*DependDefine
	BeDepends   []*BeDependDefine
	BeDependMap map[string]int

	Types           []PropType
	Map             map[string]*FieldDefine
	NoticeProp      map[string]byte
	NoticePropMap   map[byte]string
	NoticeExtend    map[structure.ExtendType]byte
	NoticeExtendMap map[byte]*ExtendDefine
	ChessProp       map[string]byte
	ChessExtend     map[structure.ExtendType]byte

	RelyField      map[string][]PropType
	ManagerInherit []string
}

func NewFieldsDefine(dataType structure.PublicDataType, key string) *FieldsDefine {
	return &FieldsDefine{
		DataType:    dataType,
		DataKey:     key,
		DependMap:   map[string]*DependDefine{},
		BeDependMap: map[string]int{},
		BeDepends:   []*BeDependDefine{},

		Types:           []PropType{},
		Map:             map[string]*FieldDefine{},
		NoticeProp:      map[string]byte{},
		NoticePropMap:   map[byte]string{},
		NoticeExtend:    map[structure.ExtendType]byte{},
		NoticeExtendMap: map[byte]*ExtendDefine{},
		ChessProp:       map[string]byte{},
		ChessExtend:     map[structure.ExtendType]byte{},

		RelyField:      map[string][]PropType{},
		ManagerInherit: []string{},
	}
}

func (fd *FieldsDefine) init(dataDefined DataDefined, fdMap map[structure.PublicDataType]*FieldsDefine) {
	fd.DataDefined = dataDefined
	for _, depend := range fd.BeDepends {
		depend.BeDependIsPosition = fd.IsPosition
		depend.BeDependIsNo = fd.IsNo
		depend.BeDependIsId = fd.IsId
		fd := fdMap[depend.DependType]
		if fd == nil {
			continue
		}
		depend.DependIsPosition = fd.IsPosition
		depend.DependIsNo = fd.IsNo
		depend.DependIsId = fd.IsId
	}
	for _, fdfd := range fdMap {
		for _, beDepend := range fdfd.BeDepends {
			if beDepend.DependType == fd.DataType {
				fd.DependMap[beDepend.Depend] = &DependDefine{
					Key:        beDepend.Depend,
					Be:         beDepend,
					IsPosition: fdfd.IsPosition,
					IsManage:   fdfd.IsManage,
					IsNo:       fdfd.IsNo,
					IsId:       fdfd.IsId,
				}
			}
		}
	}
}

type DefineFieldFunc func(fd *FieldsDefine)

func (fd *FieldsDefine) Set(dataType structure.PublicDataType, key string) *FieldsDefine {
	fd.DataType = dataType
	fd.DataKey = key
	return fd
}

func (fd *FieldsDefine) SetPosition(isPosition bool) *FieldsDefine {
	fd.IsPosition = isPosition
	return fd
}

func (fd *FieldsDefine) SetChess(isChess bool) *FieldsDefine {
	fd.IsChess = isChess
	return fd
}

func (fd *FieldsDefine) SetManage(isManage bool) *FieldsDefine {
	fd.IsManage = isManage
	return fd
}

func (fd *FieldsDefine) SetMap(isMap bool) *FieldsDefine {
	fd.IsMap = isMap
	return fd
}
func (fd *FieldsDefine) SetId(isId bool) *FieldsDefine {
	fd.IsId = isId
	return fd
}

func (fd *FieldsDefine) SetNo(isNo bool) *FieldsDefine {
	fd.IsNo = isNo
	return fd
}

// 需要确定顺序，index需要传递到chess
func (fd *FieldsDefine) BindBeDepend(beDependKey string, dataType structure.PublicDataType, dependKey string, isChess bool) *FieldsDefine {
	if _, ok := fd.BeDependMap[beDependKey]; ok {
		return fd
	}
	fd.BeDependMap[beDependKey] = len(fd.BeDepends)
	fd.BeDepends = append(fd.BeDepends, &BeDependDefine{
		Index:        fd.BeDependMap[beDependKey],
		BeDepend:     beDependKey,
		BeDependType: fd.DataType,
		Depend:       dependKey,
		DependType:   dataType,
		IsChess:      isChess,
	})
	return fd
}

func (fd *FieldsDefine) Bind(pt PropType, fun DefineFieldFunc) *FieldsDefine {
	fd.Types = append(fd.Types, pt)
	fd.inlinePropType = pt
	fun(fd)
	return fd
}

func (fd *FieldsDefine) BindNotice(fields ...string) *FieldsDefine {
	for _, field := range fields {
		if _, ok := fd.Map[field]; !ok {
			fd.Map[field] = &FieldDefine{PropType: fd.inlinePropType}
		}
		fd.NoticeProp[field] = byte(len(fd.NoticeProp))
		fd.NoticePropMap[fd.NoticeProp[field]] = field
	}
	return fd
}
func (fd *FieldsDefine) BindNoticeExtend(field structure.ExtendType, get ExtendFunc, autoClean bool) *FieldsDefine {
	if _, ok := fd.Map[string(field)]; !ok {
		fd.Map[string(field)] = &FieldDefine{PropType: fd.inlinePropType}
	}
	fd.NoticeExtend[field] = byte(len(fd.NoticeExtend))
	fd.NoticeExtendMap[fd.NoticeExtend[field]] = &ExtendDefine{
		Extend:    field,
		fun:       get,
		AutoClean: autoClean,
	}
	return fd
}
func (fd *FieldsDefine) BindChess(fields ...string) *FieldsDefine {
	for _, field := range fields {
		if _, ok := fd.Map[field]; !ok {
			fd.Map[field] = &FieldDefine{PropType: fd.inlinePropType}
		}
		//fmt.Println("fd", fd.DataType, len(fd.ChessProp), field)
		fd.ChessProp[field] = byte(len(fd.ChessProp))
	}
	return fd
}
func (fd *FieldsDefine) BindChessExtend(field structure.ExtendType) *FieldsDefine {
	if _, ok := fd.Map[string(field)]; !ok {
		fd.Map[string(field)] = &FieldDefine{PropType: fd.inlinePropType}
	}
	fd.ChessExtend[field] = byte(len(fd.ChessExtend))
	return fd
}
func (fd *FieldsDefine) BindServer(fields ...string) *FieldsDefine {
	for _, field := range fields {
		fd.Map[field] = &FieldDefine{PropType: fd.inlinePropType}
	}
	return fd
}
func (fd *FieldsDefine) BindPersistence(fields ...string) *FieldsDefine {
	for _, field := range fields {
		if _, ok := fd.Map[field]; ok {
			fd.Map[field].Persistence = true
		} else {
			fd.Map[field] = &FieldDefine{PropType: fd.inlinePropType, Persistence: true}
		}
	}
	return fd
}
func (fd *FieldsDefine) BindLocal(fields ...string) *FieldsDefine {
	for _, field := range fields {
		if _, ok := fd.Map[field]; ok {
			fd.Map[field].Local = true
		} else {
			fd.Map[field] = &FieldDefine{PropType: fd.inlinePropType, Local: true}
		}
	}
	return fd
}
func (df *FieldsDefine) Register(field string, propType PropType) {
	if _, ok := df.RelyField[field]; !ok {
		df.RelyField[field] = []PropType{propType}
	} else {
		df.RelyField[field] = append(df.RelyField[field], propType)
	}
}
